package cn.edu.imau.zy.student.controller;

import cn.edu.imau.zy.common.annotation.LoginUser;
import cn.edu.imau.zy.common.constant.ActivitiConstant;
import cn.edu.imau.zy.common.core.controller.BaseController;
import cn.edu.imau.zy.common.core.domain.R;
import cn.edu.imau.zy.common.core.entity.activiti.BizBusiness;
import cn.edu.imau.zy.common.core.entity.student.StLeave;
import cn.edu.imau.zy.common.core.entity.student.StLeaveBusinessDTO;
import cn.edu.imau.zy.common.core.entity.student.StStudent;
import cn.edu.imau.zy.common.core.entity.system.SysClasses;
import cn.edu.imau.zy.common.core.entity.system.SysUser;
import cn.edu.imau.zy.common.utils.bean.BeanUtils;
import cn.edu.imau.zy.student.service.IStLeaveService;
import cn.edu.imau.zy.system.feign.*;
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSON;
import com.google.common.collect.Maps;
import io.seata.spring.annotation.GlobalTransactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 学生请假 提供者
 *
 * @author wyz
 * @date 2020-07-01
 */
@RestController
@RequestMapping("leave")
public class StLeaveController extends BaseController {

    @Autowired
    private IStLeaveService stLeaveService;
    @Autowired
    private RemoteClassesService remoteClassesService;
    @Autowired
    private RemoteActivitiService remoteActivitiService;
    @Autowired
    private RemoteUserService remoteUserService;
    @Autowired
    private RemoteConfigService remoteConfigService;
    @Autowired
    private RemoteStudentService remoteStudentService;

    /**
     * 查询${tableComment}
     */
    @GetMapping("get/{id}")
    public StLeave get(@PathVariable("id") Long id) {
        return stLeaveService.selectStLeaveById(id);

    }

    @GetMapping("biz/{businessKey}")
    public R biz(@PathVariable("businessKey") String businessKey) {
        BizBusiness business = remoteActivitiService.getBizBusinessById(businessKey);
        if (null != business) {
            StLeave leave = stLeaveService.selectStLeaveById(Long.valueOf(business.getTableId()));
            return R.data(leave);
        }
        return R.error("no record");
    }

    /**
     * 查询学生请假列表
     */
    @GetMapping("list")
    public R list(@LoginUser SysUser user, StLeave stLeave) {
        startPage();
        List<StLeave> list;
        Map<String, BizBusiness> map;
        if (user.getRoleIds().contains(1L) || user.getRoleIds().contains(6L) || user.getRoleIds().contains(7L)) {
            //管理员 系领导 学办 查看所有
            list = stLeaveService.selectStLeaveList(stLeave);
        } else if (user.getRoleIds().contains(4L)) {
            //班主任 查看本班
            list = stLeaveService.selectStLeaveListByTeacherId(user.getUserId());
        } else if (user.getRoleIds().contains(5L)) {
            //学生 查看自己
            stLeave.setCreateBy(user.getUserId());
            list = stLeaveService.selectStLeaveList(stLeave);
        } else {
            return R.error("身份异常");
        }
        if (list.size() == 0) {
            map = new HashMap<>();
        } else {
            map = remoteActivitiService.getBizBusinessByTableIds(getIds(list));
        }

        R res = result(list);
        res.put("rows", buildBean(list, map));
        return res;
    }

    private List<StLeaveBusinessDTO> buildBean(List<StLeave> list, Map<String, BizBusiness> map) {
        List<StLeaveBusinessDTO> resList = new ArrayList<>();
        for (StLeave leave : list) {
            StLeaveBusinessDTO businessDTO = new StLeaveBusinessDTO();
            BeanUtils.copyBeanProp(businessDTO, leave);
            if (map.get(leave.getId()) != null) {
                BeanUtils.copyBeanProp(businessDTO, map.get(leave.getId()));
            }
            resList.add(businessDTO);
        }
        return resList;
    }

    private String getIds(List<StLeave> list) {
        StringBuilder sb = new StringBuilder();
        for (StLeave leave : list) {
            sb.append(leave.getId());
            sb.append(",");
        }
        sb.deleteCharAt(sb.length() - 1);
        return sb.toString();
    }

    @PostMapping("releave")
    @GlobalTransactional
    public R releave(@RequestBody Map<String, Object> params, @LoginUser SysUser user) throws Exception {
        System.out.println(params);
        if (params.get("latitude") == null && params.get("longitude") == null) {
            throw new Exception("位置信息有误");
        }
        if (params.get("leaveId") == null) {
            throw new Exception("请假ID有误");
        }
        double lat = (double) params.get("latitude");
        double lng = (double) params.get("longitude");
        long leaveId = Long.valueOf(params.get("leaveId").toString());
        //todo 地点写死，之后可能需要地点管理 暂且从configService获取
        //验证地点正确性
        if (inMap(remoteConfigService.selectConfigByKey("map.school"), lat, lng)) {
            Map<String, String> ref = remoteActivitiService.oneLatest("reLeave");
            StLeave stLeave = stLeaveService.selectStLeaveById(leaveId);

            BizBusiness business = initBusiness(stLeave, ref);
            Map<String, Object> variables = Maps.newHashMap();
            business.setVariables(variables);
            business.setTitle(user.getUserName() + "的销假申请");
            R r = remoteActivitiService.startProcess(business);
            if (!r.equals(R.ok())) {
                return R.error();
            }
            StLeave stLeave1 = new StLeave();
            stLeave1.setId(params.get("leaveId").toString());
            stLeave1.setReleaveAddress("latitude:" + lat + ",longitude:" + lng);
            stLeave1.setReleaveTime(LocalDateTime.now());
            stLeaveService.updateStLeave(stLeave1);
        } else {
            return R.error("请回到学校再进行销假~");
        }

        return R.ok();
    }

    private Boolean inMap(String map, double lat, double lng) {
        Boolean res = false;
        List<Map> list = JSON.parseArray(map).toJavaList(Map.class);
        double maxLat = -200D, maxLng = -200D, minLat = 200D, minLng = 200D;

        for (Map j : list) {
            maxLat = Double.max(maxLat, Double.valueOf(j.get("latitude").toString()));
            maxLng = Double.max(maxLng, Double.valueOf(j.get("longitude").toString()));
            minLat = Double.min(minLat, Double.valueOf(j.get("latitude").toString()));
            minLng = Double.min(minLng, Double.valueOf(j.get("longitude").toString()));
        }

        if (lat < minLat || lat > maxLat || lng < minLng || lng > maxLng) {
            return res;
        }

        for (int i = 0, j = list.size() - 1; i < list.size(); j = i++) {
            double piLat = Double.parseDouble(list.get(i).get("latitude").toString());
            double piLng = Double.parseDouble(list.get(i).get("longitude").toString());
            double pjLat = Double.parseDouble(list.get(j).get("latitude").toString());
            double pjLng = Double.parseDouble(list.get(j).get("longitude").toString());

            if (((piLat > lat) != (pjLat > lat)) &&
                    (lng < (pjLng - piLng) * (lat - piLat) / (pjLat - piLat) + piLng)) {
                res = !res;
            }
        }
        return res;
    }

    /**
     * 新增保存学生请假
     */
    @PostMapping("save")
    @GlobalTransactional
    public R addSave(@RequestBody StLeave stLeave) {
        stLeave.setCreateBy(getCurrentUserId());
        if (null == stLeave.getStartDate() || null == stLeave.getEndDate()) {
            return R.error("请选择请假时间");
        }
        if (stLeave.getStartDate().isAfter(stLeave.getEndDate())) {
            return R.error("请假时间不正确");
        }
//		if(stLeaveService.checkHave(stLeave)>0){
//            return R.error("该时段已有请假，请核对请假时间！");
//        }
        StStudent student = remoteStudentService.getStudentById(getCurrentUserId());


        stLeave.setId(IdUtil.getSnowflake(0, 0).nextIdStr());
        stLeave.setUserName(student.getStudentName());
        stLeave.setDeptId(student.getDeptId().toString());
        stLeave.setDeptName(student.getDeptName());
        stLeave.setStudentNum(student.getStudentNum());
        stLeave.setClassesId(student.getClassesId());
        stLeave.setClassesName(student.getClassesName());
        stLeave.setGrade(student.getGrade().toString());
        int row = stLeaveService.insertStLeave(stLeave);
        if (row == 1) {
            Map<String, String> ref = remoteActivitiService.oneLatest("leave");
            System.out.println(ref);
            BizBusiness business = initBusiness(stLeave, ref);
            Map<String, Object> variables = Maps.newHashMap();
            variables.put("duration", stLeave.getDuration());
            variables.put("egress", stLeave.getEgress());
            business.setVariables(variables);
            R r = remoteActivitiService.startProcess(business);
            if (!r.equals(R.ok())) {
                return R.error();
            }
        }
        return toAjax(row);
    }

    /**
     * 修改保存学生请假
     */
    @PostMapping("update")
    public R editSave(@RequestBody StLeave stLeave, @LoginUser SysUser user) {
        stLeave.setUpdateBy(user.getUserId());
        return toAjax(stLeaveService.updateStLeave(stLeave));
    }

    /**
     * 删除${tableComment}
     */
    @PostMapping("remove")
    public R remove(String ids) {
        return toAjax(stLeaveService.deleteStLeaveByIds(ids));
    }

    /**
     * @param leave
     * @return
     * @author zmr
     */
    private BizBusiness initBusiness(StLeave leave, Map<String, String> ref) {
        String userId = getCurrentUserId();
        SysUser user = remoteUserService.selectSysUserByUserId(userId);
        BizBusiness business = new BizBusiness();
        business.setTableId(leave.getId());
        business.setProcDefId(ref.get("id"));
        business.setTitle(user.getUserName() + "提交的请假");
        business.setProcName(ref.get("name"));
        business.setUserId(userId);
        business.setApplyer(user.getUserName());
        business.setStatus(ActivitiConstant.STATUS_DEALING);
        business.setResult(ActivitiConstant.RESULT_DEALING);
        business.setApplyTime(new Date());
        return business;
    }

    /**
     * 月度统计
     */
    @PostMapping("monthCount")
    public R monthCount(@RequestBody Map<String, Object> params, @LoginUser SysUser user) {
        if (params.get("year") == null || params.get("month") == null) {
            return R.error("参数错误");
        }
        if (user.getRoleIds().contains(1L) || user.getRoleIds().contains(6L) || user.getRoleIds().contains(7L)) {
            //管理员 系领导 学办 查看所有
        } else if (user.getRoleIds().contains(4L)) {
            //班主任 查看本班
            params.put("directorId", user.getUserId());
        } else if (user.getRoleIds().contains(5L)) {
            //学生 查看自己
            params.put("studentId", user.getUserId());
        } else {
            return R.error("身份异常");
        }
        Map<String, Object> res = stLeaveService.monthCount(params);
        return R.data(res);
    }

    /**
     * 每月含请假日期
     */
    @PostMapping("monthLeaveDay")
    public R monthLeaveDay(@RequestBody Map<String, Object> params, @LoginUser SysUser user) {
        if (params.get("year") == null || params.get("month") == null) {
            return R.error("参数错误");
        }
        if (user.getRoleIds().contains(1L) || user.getRoleIds().contains(6L) || user.getRoleIds().contains(7L)) {
            //管理员 系领导 学办 查看所有
        } else if (user.getRoleIds().contains(4L)) {
            //班主任 查看本班
            params.put("directorId", user.getUserId());
        } else if (user.getRoleIds().contains(5L)) {
            //学生 查看自己
            params.put("studentId", user.getUserId());
        } else {
            return R.error("身份异常");
        }
        return R.data(stLeaveService.monthLeaveDay(params));
    }

    /**
     * 每日请假列表
     */
    @GetMapping("dayLeave")
    public R dayLeave(@RequestParam Map<String, Object> params, @LoginUser SysUser user) {
        if (params.get("date") == null) {
            return R.error("参数错误");
        }
        if (user.getRoleIds().contains(1L) || user.getRoleIds().contains(7L)) {
            //管理员 学生处 查看所有
        } else if (user.getRoleIds().contains(6L)) {
            //系领导 查看本系
            params.put("deptId", user.getDeptId());
        } else if (user.getRoleIds().contains(4L)) {
            //班主任 查看本班
            List<SysClasses> clList = remoteClassesService.jList();
            List<String> ids = clList.stream().map(p -> p.getClassesId()).collect(Collectors.toList());
            params.put("classesIds", ids);
        } else {
            return R.error("身份异常");
        }

        return R.data(stLeaveService.dayLeave(params));
    }

    /**
     * 按系统计 图表
     */
    @PostMapping("deptLeave")
    public R deptLeave(@LoginUser SysUser user) {
        return R.data(stLeaveService.deptLeave());
    }

    /**
     * 按系-年级统计 图表
     */
    @PostMapping("deptGreadLeave")
    public R deptGreadLeave(@RequestBody Map<String, Object> params, @LoginUser SysUser user) {
        return R.data(stLeaveService.deptGreadLeave(params));
    }

    /**
     * 按班级 系-年级-统计 图表
     */
    @PostMapping("classesLeave")
    public R classesLeave(@RequestBody Map<String, Object> params, @LoginUser SysUser user) {
        if (user.getRoleIds().contains(1L) || user.getRoleIds().contains(6L) || user.getRoleIds().contains(7L)) {
            //管理员 系领导 学办 查看所有
        } else if (user.getRoleIds().contains(4L)) {
            //班主任 查看本班
            params.put("directorId", user.getUserId());
        } else {
            return R.error("身份异常");
        }
        System.out.println(params);
        return R.data(stLeaveService.classesLeave(params));
    }

    /**
     * 按班级 学生 图表
     */
    @PostMapping("classesDetailLeave")
    public R classesDetailLeave(@RequestBody Map<String, Object> params, @LoginUser SysUser user) {
        return R.data(stLeaveService.classesDetailLeave(params));
    }

    /**
     * 请销假统计
     *
     * @return
     */
    @GetMapping("countInged")
    public R countInged(@RequestParam Map<String, Object> params, @LoginUser SysUser user) {
        if (user.getRoleIds().contains(1L) || user.getRoleIds().contains(7L)) {
            //管理员 学生处 查看所有
        } else if (user.getRoleIds().contains(6L)) {
            //系领导 查看本系
            params.put("deptId", user.getDeptId());
        } else if (user.getRoleIds().contains(4L)) {
            //班主任 查看本班
            List<SysClasses> clList = remoteClassesService.jList();
            List<String> ids = clList.stream().map(p -> p.getClassesId()).collect(Collectors.toList());
            params.put("classesIds", ids);
        } else {
            return R.error("身份异常");
        }
        return R.data(stLeaveService.countInged(params));
    }
}
